#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <hiredis/hiredis.h>
#include "idc_ubus_energy.h"
#include "idc_ubus_common.h"
#include "crc.h"
#include "frame_util.h"
#include "protocol.h"
#include "lora_service.h"
#include "data_type.h"
#include <time.h>
#include <semaphore.h>
#include "hash_map.h"
extern HashMap *online_devs;

extern pShartData ubus_cmd_Psd;
char* double_to_string_fixed(double value) {
    int length = snprintf(NULL, 0, "%.3f", value) + 1;
    char* buffer = (char*)malloc(length);
    snprintf(buffer, length, "%.3f", value);
    return buffer;
}

/**
 * 设置休眠时间
 */ 
int set_sleep(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
        struct blob_attr *tb[3];
        blobmsg_parse(set_sleep_wake_policy, 3, tb, blob_data(msg), blob_len(msg));
        blob_buf_init(&b, 0);
        if(tb[0] && tb[1] && tb[2])
        {
                int hours = blobmsg_get_u32(tb[0]);
                int minutes = blobmsg_get_u32(tb[1]);
                int seconds = blobmsg_get_u32(tb[2]);
                uint8_t output[10];
                uint16_t len = protocol_encode(0xA5, 0x0A, (uint8_t[]){hours & 0xFF, minutes & 0xFF, seconds & 0xFF}, 3, output);
                lora_send(output, len);
        }
        return 0;
} 
/**
 * 设置唤醒时间
 */
int set_work(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
        struct blob_attr *tb[3];
        blobmsg_parse(set_sleep_wake_policy, 3, tb, blob_data(msg), blob_len(msg));
        blob_buf_init(&b, 0);
        if(tb[0] && tb[1] && tb[2])
        {
                int hours = blobmsg_get_u32(tb[0]);
                int minutes = blobmsg_get_u32(tb[1]);
                int seconds = blobmsg_get_u32(tb[2]);
                uint8_t output[10];
                uint16_t len = protocol_encode(0xA5, 0x0B, (uint8_t[]){hours & 0xFF, minutes & 0xFF, seconds & 0xFF}, 3, output);
                lora_send(output, len);
        }
        return 0;
} 

int sync_timer(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        time_t current_timestamp = time(NULL);
        uint8_t output[14];
        uint16_t len = protocol_encode(0xA5, 0x09, (uint8_t[]){current_timestamp >> 24 & 0xFF, current_timestamp >> 16 & 0xFF, \
                current_timestamp >> 8 & 0xFF, current_timestamp & 0xFF}, 4, output);
        lora_send(output, len);
        return 0;
}

int set_energy_id(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[2];
        blobmsg_parse(entry_set_addr_policy, 2, tb, blob_data(msg), blob_len(msg));
        if (tb[0] && tb[1]) {
                const char *addr = blobmsg_get_string(tb[0]);
                const char *group_addr = blobmsg_get_string(tb[1]);
                uint16_t hex_addr, hex_group_addr;
                uint8_t data[4];
                if (sscanf(addr, "%hX", &hex_addr) == 1) {
                        data[0] = (hex_addr >> 8) & 0xFF;
                        data[1] = hex_addr & 0xFF;
                } else {
                        printf("addr 转换失败\n");
                        return 0;
                }
                if (sscanf(group_addr, "%hX", &hex_group_addr) == 1) {
                        data[2] = (hex_group_addr >> 8) & 0xFF;
                        data[3] = hex_group_addr & 0xFF;
                } else {
                        printf("group_addr 转换失败\n");
                        return 0;
                }
                uint8_t output[17];
                uint16_t len = protocol_encode(0xA5, 0x05, data, 4, output);
                lora_send(output, len);
        }
        return 0;
}

int control_work(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+POWER=1\r\n");
        uint8_t output[8];
        uint16_t len = protocol_encode(0xA5, 0x03, (uint8_t[]){0x01}, 1, output);
        lora_send(output, len);
        return 0;
}

int control_sleep(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        //lora_printf("AT+POWER=0\r\n");

        uint8_t output[8];
        uint16_t len = protocol_encode(0xA5, 0x03, (uint8_t[]){0x00}, 1, output);
        lora_send(output, len);
        return 0;
}
/**
 * 重启MT7621模块
 * 
 */
int reset_mt7621(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[8];
        uint16_t len = protocol_encode(0xA5, 0x0E, NULL, 0, output);
        lora_send(output, len);
        return 0;
}
/**
 * 设置7621运行模式；mode为0表示运行模式，mode为1表示升级模式（电源模块不检测心跳）
 * 
 */
int set_mt7621_run_mode(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        struct blob_attr *tb[1];
        blobmsg_parse(set_mt7621_run_mode_policy, 1, tb, blob_data(msg), blob_len(msg));
        if (tb[0]) {
                blob_buf_init(&b, 0);
                int mode = blobmsg_get_u32(tb[0]);
                uint8_t output[9];
                uint16_t len = protocol_encode(0xA5, 0x0D, (uint8_t[]){mode & 0xFF}, 1, output);
                lora_send(output, len);
        }
        return 0;
}
int query_timeinfo(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        blob_buf_init(&b, 0);
        uint8_t output[7];
        uint16_t len = protocol_encode(0xA5, 0x0C, NULL, 0, output);
        lora_send(output, len);

        // sem_wait(&ubus_cmd_Psd.sem);
        // 设置超时时间（3秒）
        struct timespec ts;
        if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {
                perror("获取时间失败");
                sem_destroy(&ubus_cmd_Psd.sem);
                return 1;
        }
        ts.tv_sec += 3; // 3秒超时
        
        // 使用sem_timedwait等待信号量（带超时）
        int result = sem_timedwait(&ubus_cmd_Psd.sem, &ts);
        
        if (result == -1) {
                if (errno == ETIMEDOUT) {
                        printf("等待超时！资源在3秒内未释放\n");
                } else {
                        perror("sem_timedwait失败");
                }
        } else {
                pthread_mutex_lock(&ubus_cmd_Psd.mutex); // 加锁
                uint8_t date[22]={0},sleep_time[10]={0},work_time[10]={0}, run_time[25] = {0};

                time_t timestamp = (ubus_cmd_Psd.data[2]<<24 | ubus_cmd_Psd.data[3]<<16|ubus_cmd_Psd.data[4]<<8|ubus_cmd_Psd.data[5]);

                struct tm *energy_date = localtime(&timestamp);
                strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", energy_date);

                sprintf(sleep_time, "%02d:%02d:%02d",ubus_cmd_Psd.data[6],ubus_cmd_Psd.data[7],ubus_cmd_Psd.data[8]);
                sprintf(work_time, "%02d:%02d:%02d",ubus_cmd_Psd.data[9],ubus_cmd_Psd.data[10],ubus_cmd_Psd.data[11]);

                uint32_t run_timestamp = ((ubus_cmd_Psd.data[12]<<24 & 0xFF000000) | (ubus_cmd_Psd.data[13]<<16 & 0xFF0000) |\
                                 (ubus_cmd_Psd.data[14]<<8 & 0xFF00) | ubus_cmd_Psd.data[15]);
                RuntimeCounter *runtime = RuntimeCounter_Update(run_timestamp);

                sprintf(run_time, "%lu days %02d:%02d:%02d",runtime->days, runtime->hours, runtime->minutes,runtime->seconds);
                
                blobmsg_add_u32(&b, "addr", (ubus_cmd_Psd.data[0]<<8 | ubus_cmd_Psd.data[1]));
                blobmsg_add_string(&b, "date", date);
                blobmsg_add_string(&b, "sleep_time", sleep_time);
                blobmsg_add_string(&b, "work_time", work_time);
                blobmsg_add_string(&b, "run_time", run_time);
                ubus_send_reply(ctx, req, b.head);
                free(runtime);
                pthread_mutex_unlock(&ubus_cmd_Psd.mutex); // 解锁
        }
        return 0;
}
/**
 * LoRa模块网络初始化
 * 
 */
int test_lora(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        uint8_t output[7];
        uint16_t len = protocol_encode(0xA5, 0x0D, NULL, 0, output);
        lora_send(output, len);
        return 0;
}

char *float2str(float f) {
        char *str = malloc(10);
        memset(str, 0, 10);
        sprintf(str, "%.2f", f);
        return str;
}

// 用于测试map_iterate_keys的回调函数
void print_key_callback(const char *key, void *context) {
    printf("键: %s\n", key);
}
int read_devs(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg){
        blob_buf_init(&b, 0);
        void *arr = blobmsg_open_array(&b, "result"); // 在表中创建"result"字段的数组
        // map_iterate_keys(online_devs, print_key_callback, NULL);
        char **keys = map_keys(online_devs);
        if (keys) {
                printf("✅ 获取键数组成功\n");
                printf("所有键:\n");
                for (size_t i = 0; keys[i] != NULL; i++) {
                        printf("  - %s\n", keys[i]);
                        HeartData heart;
                        char *str = map_get(online_devs, keys[i]);
                        if(str != NULL){
                                int parsed = sscanf(str,"+HEART:%hX,%hX,%hX,%d,%f,%f,%hd,%d,%f,%f,%f,%d,%f,%d,%d,%d,%d,%d,%d,%d,%d,%d,%f,%f,%ld\r\n",
                                &heart.addr, &heart.group_addr, &heart.trans_addr, &heart.status,&heart.batteryVoltage,&heart.batteryElectric,&heart.batteryCapacity,
                                &heart.batteryStatus,&heart.loadVoltage,&heart.loadElectric,&heart.loadPower,&heart.loadStatus,&heart.columnVoltage,&heart.columnStatus,
                                &heart.runDay,&heart.lowVolCnt,&heart.todayDischarge,&heart.yesterdayDischarge,&heart.totalDischarge,&heart.todayCharge,
                                &heart.yesterdayCharge,&heart.totalCharge,&heart.fDevTemperature,&heart.fBatTemperature,&heart.seconds);
                                if(parsed == 25) {
                                        void *tbl = blobmsg_open_table(&b, NULL); // 打开一个匿名表作为顶层
                                        char num[5] = {0}, group_addr[4]={0}, trans_addr[4]={0};
                                        sprintf(num, "%04X", heart.addr);
                                        blobmsg_add_string(&b, "sn", num);
                                        sprintf(group_addr, "%04X", heart.group_addr);
                                        blobmsg_add_string(&b, "group_addr", group_addr);
                                        sprintf(trans_addr, "%04X", heart.trans_addr);
                                        blobmsg_add_string(&b, "trans_addr", trans_addr);
                                        blobmsg_add_u32(&b, "powerStatus", heart.status);
                                        char *batteryVoltage = float2str(heart.batteryVoltage);
                                        blobmsg_add_string(&b, "batteryVoltage", batteryVoltage);
                                        free(batteryVoltage);
                                        char *batteryElectric = float2str(heart.batteryElectric);
                                        blobmsg_add_string(&b, "batteryElectric", batteryElectric);
                                        free(batteryElectric);
                                        blobmsg_add_u16(&b, "batteryCapacity", heart.batteryCapacity);
                                        blobmsg_add_u32(&b, "batteryStatus", heart.batteryStatus);
                                        char *loadVoltage = float2str(heart.loadVoltage);
                                        blobmsg_add_string(&b, "loadVoltage", loadVoltage);
                                        free(loadVoltage);
                                        char *loadPower = float2str(heart.loadPower);
                                        blobmsg_add_string(&b, "loadPower", loadPower);
                                        free(loadPower);
                                        blobmsg_add_u32(&b, "loadStatus", heart.loadStatus);
                                        char *columnVoltage = float2str(heart.columnVoltage);
                                        blobmsg_add_string(&b, "columnVoltage", columnVoltage);
                                        free(columnVoltage);
                                        blobmsg_add_u32(&b, "columnStatus", heart.columnStatus);
                                        blobmsg_add_u32(&b, "runDay", heart.runDay);
                                        blobmsg_add_u32(&b, "lowVolCnt", heart.lowVolCnt);
                                        blobmsg_add_u32(&b, "todayDischarge", heart.todayDischarge);
                                        blobmsg_add_u32(&b, "yesterdayDischarge", heart.yesterdayDischarge);
                                        blobmsg_add_u32(&b, "totalDischarge", heart.totalDischarge);
                                        blobmsg_add_u32(&b, "todayCharge", heart.todayCharge);
                                        blobmsg_add_u32(&b, "yesterdayCharge", heart.yesterdayCharge);
                                        blobmsg_add_u32(&b, "totalCharge", heart.totalCharge);
                                        blobmsg_add_u32(&b, "seconds", heart.seconds);
                                                char *fDevTemperature = float2str(heart.fDevTemperature);
                                        blobmsg_add_string(&b, "fDevTemperature", fDevTemperature);
                                        free(fDevTemperature);
                                                char *fBatTemperature = float2str(heart.fBatTemperature);
                                        blobmsg_add_string(&b, "fBatTemperature", fBatTemperature);
                                        free(fBatTemperature);
                                        blobmsg_close_table(&b, tbl);
                                }
                        }
                }
                // 释放键数组
                map_free_keys(keys);
                printf("✅ 键数组已释放\n");
        } else {
                printf("❌ 获取键数组失败\n");
        }
        blobmsg_close_array(&b, arr);
        ubus_send_reply(ctx, req, b.head);
}